#include "describe.h"
#include <stdlib.h>
#include <glib-object.h>

typedef struct _DescribeValue {
  GObject parent_instance;

  gchar *class;

  gint64 id;
  gint64 parentID;

  gchar *describe;
  gchar *name;
  gchar *nameAlias;
  gchar *typeName;

  GObject *son;
  GObject *parent;
  GObject *next;

  gpointer userdata;
} DescribeValue;
enum {
  PROP_0,
  PROP_CLASS,
  PROP_ID, PROP_PARENT_ID,
  PROP_DESCRIBE, PROP_NAME, PROP_NAME_ALIAS, PROP_TYPE_NAME,
  PROP_SON, PROP_PARENT, PROP_NEXT,
  PROP_USERDATA,
  N_PROPERTIES };

static GParamSpec *properties[N_PROPERTIES] = { NULL, };

G_DEFINE_TYPE(DescribeValue, describe_value, G_TYPE_OBJECT)
//int64
static void describe_value_set_id(DescribeValue *obj, gint64    value)
{
  if (obj->id != value)
    {
      obj->id = value;

      g_assert(properties[PROP_ID] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_ID]);
    }
}
static void describe_value_set_parentID(DescribeValue *obj,
    gint64    value)
{
  if (obj->parentID != value)
    {
      obj->parentID = value;

      g_assert(properties[PROP_PARENT_ID] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_PARENT_ID]);
    }
}
static void
describe_value_set_describe(DescribeValue  *obj, const gchar *value)
{
  if (g_strcmp0(obj->describe, value) != 0)
    {
      g_free(obj->describe);
      obj->describe = g_strdup(value);

      g_assert(properties[PROP_DESCRIBE] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_DESCRIBE]);
    }
}
static void describe_value_set_class(DescribeValue *obj, const gchar *value)
{
  if (g_strcmp0(obj->class, value) != 0)
    {
      g_free(obj->class);
      obj->class = g_strdup(value);

      g_assert(properties[PROP_CLASS] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_CLASS]);
    }
}
static void
describe_value_set_name(DescribeValue  *obj,
                      const gchar *value)
{
  if (g_strcmp0(obj->name, value) != 0)
    {
      g_free(obj->name);
      obj->name = g_strdup(value);

      g_assert(properties[PROP_NAME] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_NAME]);
    }
}
static void
describe_value_set_typeName(DescribeValue  *obj,
                      const gchar *value)
{
  if (g_strcmp0(obj->typeName, value) != 0)
    {
      g_free(obj->typeName);
      obj->typeName = g_strdup(value);

      g_assert(properties[PROP_TYPE_NAME] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_TYPE_NAME]);
    }
}
static void
describe_value_set_nameAlias(DescribeValue  *obj,
                      const gchar *value)
{
  if (g_strcmp0(obj->nameAlias, value) != 0)
    {
      g_free(obj->nameAlias);
      obj->nameAlias = g_strdup(value);

      g_assert(properties[PROP_NAME_ALIAS] != NULL);
      g_object_notify_by_pspec(G_OBJECT(obj), properties[PROP_NAME_ALIAS]);
    }
}
//object
static void
describe_value_set_next(DescribeValue  *obj,
                      gpointer next)
{
    obj->next = next;
}
static void
describe_value_set_son(DescribeValue  *obj,
                      gpointer son)
{
    obj->son = son;
}
static void
describe_value_set_parent(DescribeValue  *obj,
                      gpointer value)
{
    obj->parent = value;
}
static void
describe_value_set_userdata(DescribeValue  *obj,
                      gpointer value)
{
    obj->userdata = value;
}

static void
describe_value_finalize(GObject *gobject)
{
  DescribeValue *self = (DescribeValue *) gobject;

  if (self->next)
    g_object_unref(self->next);
  if (self->son)
    g_object_unref(self->son);

  if (self->describe)
    g_free(self->describe);
  if (self->name)
    g_free(self->name);
  if (self->nameAlias)
    g_free(self->nameAlias);
  if (self->typeName)
    g_free(self->typeName);
  if (self->class)
    g_free(self->class);

  g_object_notify(gobject, "port");
  G_OBJECT_CLASS(describe_value_parent_class)->finalize(gobject);
}

static void
describe_value_set_property(GObject *gobject,
                          guint prop_id,
                          const GValue *value,
                          GParamSpec *pspec)
{
  DescribeValue *tobj = (DescribeValue *) gobject;

  g_assert_cmpint(prop_id, !=, 0);
  g_assert_cmpint(prop_id, !=, N_PROPERTIES);
  g_assert(pspec == properties[prop_id]);

  switch (prop_id)
    {
    case PROP_ID:
      describe_value_set_id(tobj, g_value_get_int64(value));
      break;
    case PROP_PARENT_ID:
      describe_value_set_parentID(tobj, g_value_get_int64(value));
      break;

    case PROP_DESCRIBE:
      describe_value_set_describe(tobj, g_value_get_string(value));
      break;
    case PROP_NAME:
      describe_value_set_name(tobj, g_value_get_string(value));
      break;
    case PROP_NAME_ALIAS:
      describe_value_set_nameAlias(tobj, g_value_get_string(value));
      break;
    case PROP_TYPE_NAME:
      describe_value_set_typeName(tobj, g_value_get_string(value));
      break;
    case PROP_CLASS:
      describe_value_set_class(tobj, g_value_get_string(value));
      break;

    case PROP_NEXT:
      describe_value_set_next(tobj, g_value_get_pointer(value));
      break;
    case PROP_SON:
      describe_value_set_son(tobj, g_value_get_pointer(value));
      break;
    case PROP_PARENT:
      describe_value_set_parent(tobj, g_value_get_pointer(value));
      break;
    case PROP_USERDATA:
      describe_value_set_userdata(tobj, g_value_get_pointer(value));
      break;

    default:
      g_assert_not_reached();
    }
}

static void
describe_value_get_property(GObject *gobject,
                          guint prop_id,
                          GValue *value,
                          GParamSpec *pspec)
{
  DescribeValue *tobj = (DescribeValue *)gobject;

  g_assert_cmpint(prop_id, !=, 0);
  g_assert_cmpint(prop_id, !=, N_PROPERTIES);
  g_assert(pspec == properties[prop_id]);

  switch (prop_id)
    {
    case PROP_ID:
      g_value_set_int64(value, tobj->id);
      break;
    case PROP_PARENT_ID:
      g_value_set_int64(value, tobj->id);
      break;

    case PROP_DESCRIBE:
      g_value_set_string(value, tobj->describe);
      break;
    case PROP_NAME:
      g_value_set_string(value, tobj->name);
      break;
    case PROP_NAME_ALIAS:
      g_value_set_string(value, tobj->nameAlias);
      break;
    case PROP_TYPE_NAME:
      g_value_set_string(value, tobj->typeName);
      break;
    case PROP_CLASS:
      g_value_set_string(value, tobj->class);
      break;

    case PROP_NEXT:
      g_value_set_pointer(value, tobj->next);
      break;
    case PROP_SON:
      g_value_set_pointer(value, tobj->son);
      break;
    case PROP_PARENT:
      g_value_set_pointer(value, tobj->parent);
      break;
    case PROP_USERDATA:
      g_value_set_pointer(value, tobj->userdata);
      break;
    default:
      g_assert_not_reached();
    }
}

static void
describe_value_class_init(DescribeValueClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS(klass);

  properties[PROP_ID] = g_param_spec_int64("id", "id", "Id",
      -1, G_MAXINT64, 0, G_PARAM_READWRITE);
  properties[PROP_PARENT_ID] = g_param_spec_int64(
      "parentID", "ParentId", "parent_Id",
      -1, G_MAXINT64, 0, G_PARAM_READWRITE);

  properties[PROP_DESCRIBE] = g_param_spec_string(
      "describe", "describe", "describe",
      NULL, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
  properties[PROP_NAME] = g_param_spec_string(
      "name", "name", "name",
      NULL, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
  properties[PROP_NAME_ALIAS] = g_param_spec_string(
      "nameAlias", "nameAlias", "nameAlias",
      NULL, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
  properties[PROP_TYPE_NAME] = g_param_spec_string(
      "typeName", "TypeName", "TYPENAME",
      NULL, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
  properties[PROP_CLASS] = g_param_spec_string(
      "class", "Class", "CLASS",
      NULL, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);

  properties[PROP_SON] = g_param_spec_pointer("son", "son", "son",
      G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
  properties[PROP_NEXT] = g_param_spec_pointer("next", "next", "next",
      G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
  properties[PROP_PARENT] = g_param_spec_pointer("parent", "parent", "parent",
      G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
  properties[PROP_USERDATA] = g_param_spec_pointer(
      "userdata", "userdata", "userdata",
      G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);

  gobject_class->set_property = describe_value_set_property;
  gobject_class->get_property = describe_value_get_property;
  gobject_class->finalize = describe_value_finalize;

  g_object_class_install_properties(gobject_class, N_PROPERTIES, properties);
}

static void describe_value_init(DescribeValue *self)
{
}
DescribeValue *describe_value_new(void)
{
  return g_object_new(DESCRIBE_VALUE_TYPE, NULL);
}
